<?php
/*******************************************
	User procedures
*******************************************/

// Avoid direct access
if(substr_count($_SERVER['PHP_SELF'], 'user.php') > 0) {
	header("HTTP/1.0 404 Not Found");
	exit;
}


// requires: THEY ARE ALREADY INSIDE THE CONFIG FILE
	// curl.php -> parent class
	// security.php -> security procedures

class User extends Curl {

	public $isLogged 	= false;	// by default a user is NOT logged
	public $session_id	= null;
	public $user_id		= null;
	public $username	= null;
	public $password	= null;
	
	public $error		= null;		// last error
	
	

	function __construct() {
	
		parent::__construct();
	
		// USER'S SESSION
		if(!empty($_GET['PHPSESSID'])) {
			session_id(htmlspecialchars($_GET['PHPSESSID']));
			session_start();
			// security check
			if( ($_SESSION['userIsLogged'] == "YES") && ($_SESSION['userAgent'] == $_SERVER["HTTP_USER_AGENT"]) && ($_SESSION['userIP'] == Security::get_user_ip()) ) {
				$this->isLogged = true;	
				
				$this->username = Security::decrypt_string($_SESSION['username']);
				$this->password = Security::decrypt_string($_SESSION['password']);

				$this->user_id 	= $_SESSION['user_id'];
			}		
			
		} else {
			$this->isLogged = false;	
			session_unregister('userIsLogged');
			session_regenerate_id(true);
			session_destroy();
		}		
	
	}
	
	
	
	/* Try login */
	function login($user, $password) {
	
		$this->error = null;
		
		$user_id = $this->get_user_id($user, $password);
			
		// found
		if($user_id !== false) {
			$this->user_id = (int)$user_id;
			$this->isLogged = true;
			$this->username = $user;
			$this->password = $password;
			$this->init_user();

			return true;
		}
	
		$this->error = Content::ERROR_INCORRECT_LOGIN;
		return false;
	
	}
	
	/* logout */
	function logout() {

		$this->isLogged		= false;
		$this->session_id	= null;
		$this->user_id		= null;
		$this->username		= null;
		$this->password		= null;		

		// to be 100% sure the logout will work, I change also the sessio n_id
		session_regenerate_id(true);
		session_destroy();
	}
	
	
	/* Init user session */
	protected function init_user() {
		
		// destroy old session (if any)
		session_regenerate_id(true);
		session_destroy();
		// new session
		session_start();
		$this->session_id = session_id();
		// session variables
			// userIsLogged: indicates the user is ged
			session_register("userIsLogged");
			$_SESSION['userIsLogged'] = "YES";
			// userAgent: indicates the user agent of the browser (for security reasons)
			session_register("userAgent");
			$_SESSION['userAgent'] = $_SERVER["HTTP_USER_AGENT"];
			// userIP: idicates the user IP or hostname (for security reasons)
			session_register("userIP");
			$_SESSION['userIP'] = Security::get_user_ip();
			
		//  user's data
			// username: crypted to improve security
			session_register("username");
			$_SESSION['username'] = Security::crypt_string($this->username);		
			// password: crypted to improve security
			session_register("password");
			$_SESSION['password'] = Security::crypt_string($this->password);	
			// User ID
			session_register("user_id");
			$_SESSION['user_id'] = $this->user_id;	

	}
	

	/* Get the User ID */
	protected function get_user_id($user = null, $password = null, $ch = null) {

		// use saved data
		if(is_null($user)) $user = $this->user;
		if(is_null($password)) $password = $this->password;
		if(is_null($ch)) $ch = $this->init();		

		$this->error = null;

		
		curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/users/login");
		$result = curl_exec ($ch);
	
		curl_setopt ($ch, CURLOPT_POSTFIELDS, "login_username=$user&login_password=$password&_action_login");
		curl_setopt ($ch, CURLOPT_POST, 1);
		curl_setopt ($ch, CURLOPT_REFERER, HTTP."/cgi/users/login");
		$result = curl_exec ($ch);	
	
		if( (substr_count($result, "Logged in as") > 0) && (substr_count($result, '<span class="person_name">') > 0 ) ) {
		
			// Go to the right page and look for the user id
			curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/users/home?screen=User::View");
			curl_setopt ($ch, CURLOPT_POST, 0);
			curl_setopt ($ch, CURLOPT_REFERER, HTTP."/cgi/users/login");
			$result = curl_exec ($ch);
			
			$user_id = "";
			$xml = new SimpleXMLElement($result);
			$result = $xml->xpath("//input[@id='userid']");
			
			if( ($result !== false) && (count($result) > 0)){
		
				foreach($result[0]->attributes() as $attribute => $value) {
				    if($attribute == "value") {
				    	$user_id = $value;
				    	break;
				    }
				}
				
				// found
				if($user_id != "") {
				
					return $user_id;

				}
			}

		}
	
		$this->error = Content::ERROR_INCORRECT_LOGIN;
		return false;
	
	}	
	
	
	/* Register */ 
	function register($email="", $password="", $title="", $name="", $surname="") {

		$this->error = null;
		
		// Since there are bugs in EPRint, we have to check before to send the data
		
		// Verify email before even send data
		if(!filter_var($email, FILTER_VALIDATE_EMAIL))
		{
			$this->error = Content::ERROR_INCORRECT_EMAIL;
			return false;
		}
		
		if($name == "") {
			$this->error = Content::ERROR_INCORRECT_NAME;	
			return false;
		}
		if($surname == "") {
			$this->error = Content::ERROR_INCORRECT_SURNAME;	
			return false;
		}	
		if($password == "") {
			$this->error = Content::ERROR_INCORRECT_PWD;	
			return false;
		}		
		
		$ch = $this->init();
		
		curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/register");
		$result = curl_exec ($ch);
	
		curl_setopt ($ch, CURLOPT_POSTFIELDS, "_default_action=submit&email=$email&name_honourific=$title&name_given=$name&name_family=$surname&newpassword=$password&_seen=true&_action_submit=Register&mobi_conf=".MOBILE."/activate-user-account");
		curl_setopt ($ch, CURLOPT_POST, 1);
		curl_setopt ($ch, CURLOPT_REFERER, HTTP."/cgi/register");
		$result = curl_exec ($ch);
		
		$error = false;
		if( (substr_count($result, "You have registered with username") > 0) && (substr_count($result, 'you visit the confirmation URL') > 0 ) ) {
			return true;
		} else {
	
			$error = "";
	
			// Look for a more specific error
			$xml = new SimpleXMLElement($result);
			$result = $xml->xpath("//div[@class='ep_msg_error_content']/table/tr");
		
			if(is_array($result)) {
				foreach ($result[0]->children() as $child)
				{
					if($error != "") break;
					foreach($child as $tag=>$value) {
						if($tag == "p") {
							if(substr_count($value, "already exists") > 0) {
								$error = str_replace("XX__EMAIL__XX", $email, Content::ERROR_EMAIL_EXIST);
								break;
							} else if(substr_count($value, 'You have not filled in the "Your email address" field') > 0) {
								$error = Content::ERROR_INCORRECT_EMAIL2;
								break;
							} else if(substr_count($value, 'You have not filled in the "Select a password" field') > 0) {
								$error = Content::ERROR_INCORRECT_PWD;
								break;
							} else if(substr_count($value, 'You have not filled in the "Your name" field') > 0) {
								$error = Content::ERROR_INCORRECT_NAME;
								break;
							}
				  		}
				  	}
				}
			}
		}
	
		if($error == "") {
			// generic error
			$error = Content::ERROR_GENERIC;
		}
		
		$this->error = $error;
		return false;
	
	}
	
	
	/* Activate user profile */
	function activate_profile($uri) {
		$this->error = null;
		
		$ch = $this->init();
		
		curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/confirm".$uri);
		$result = curl_exec ($ch);
	
		if( (substr_count($result, "no changes") > 0 ) || (substr_count($result, "not found") > 0 ) || (substr_count($result, "Bad parameters") > 0 ) ){
		
			$this->error = Content::REGISTER_NOSUCCESS;
		
			return false;
		}
	
		return true;
		
	}
	
		
	/* Get profile info */
	function get_profile() {
	
		$this->error = null;
	
		$ch = $this->init();
		$user_id = $this->get_user_id($this->username, $this->password, &$ch);
			
		// found
		if($user_id !== false) {
			
			curl_setopt ($ch, CURLOPT_POST, 0);
			curl_setopt ($ch, CURLOPT_REFERER, HTTP."/cgi/users/home?screen=User::View");
			curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/users/home?screen=User%3A%3AEdit&userid=$user_id&_action_null=Modify+profile");
			$result = curl_exec ($ch);
			
			// I need to find all the fields and save the values
			$user_data = array();
			$xml = new SimpleXMLElement($result);
			
			// inputs
			$fields = $xml->xpath("//div[@id='content']//form//input");
	
			for($i=0; $i<count($fields); $i++) {
				$input	= array();
				$name	= "";
				foreach($fields[$i]->attributes() as $attribute => $value) {
				    if((substr_count($attribute, "class") == 0) && (substr_count($attribute, "on") == 0)) {			    	
				    	if($attribute == "name") {
				    		$name = (string)$value;
				    	} else {
				    		$input[(string)$attribute] = (string)$value;
				    	}
				    }
				}
				if(!array_key_exists($name, $user_data))
					$user_data[$name] = $input;
			}	

			
			// text areas
			$fields = $xml->xpath("//div[@id='content']//form//textarea");
	
			for($i=0; $i<count($fields); $i++) {
				$input	= array();
				$name	= "";
				foreach($fields[$i]->attributes() as $attribute => $value) {
				    if((substr_count($attribute, "class") == 0) && (substr_count($attribute, "on") == 0)) {
				    	if($attribute == "name") {
				    		$name = (string)$value;
				    	} else {
				    		$input[(string)$attribute] = (string)$value;
				    	}
				    }
				}
				$input["value"] = (string)$fields[$i][0];
				$input["type"] = "textarea";
				$user_data[$name] = $input;
			}	
			
			if(count($user_data) > 0)
				return $user_data;			

			
		}
	
		$this->error = Content::ERROR_RETRIVE;
		return false;
	
	}	
	
	
	/* Set profile info */
	function set_profile(array $post_data, array $required_fields, array $url_fields, $pwd_field) {
	
		$this->error = null;
		
		// Since there are bugs in EPRint, we have to check before to send the data
		// required fields
		foreach($required_fields as $name => $error_string) {
			if($_POST[$name] == "") {
				$this->error = str_replace("XX__ERROR__XX", $error_string, Content::ERROR_ERROR);
				return false;
			}
		}
		// url fields
		foreach($url_fields as $name => $error_string) {
			if($_POST[$name] != "") {	// only if not empty
				if(!filter_var($_POST[$name], FILTER_VALIDATE_URL)) {
					$this->error = str_replace("XX__ERROR__XX", $error_string, Content::ERROR_NOT_VALID);
					return false;
				}
			}
		}		
		
		//  create post data string
		$new_post_data = "";
		foreach($post_data as $param => $value) {
			if($post_data == "") {
				$new_post_data .= $param."=".(htmlspecialchars_decode($value, ENT_QUOTES));
			} else {
				$new_post_data .= "&".$param."=".(htmlspecialchars_decode($value, ENT_QUOTES));
			}
		}
		$post_data = $new_post_data;
		
		
		$ch = $this->init();
		$user_id = $this->get_user_id($this->username, $this->password, &$ch);
			
		// found
		if($user_id !== false) {
			
			// referer cookies
			curl_setopt ($ch, CURLOPT_POST, 0);
			curl_setopt ($ch, CURLOPT_REFERER, HTTP."/cgi/users/home?screen=User::View");
			curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/users/home?screen=User%3A%3AEdit&userid=$user_id&_action_null=Modify+profile");
			$result = curl_exec ($ch);		
		
			// Update user info
			curl_setopt ($ch, CURLOPT_POST, 1);
			curl_setopt ($ch, CURLOPT_POSTFIELDS, $post_data);
			curl_setopt ($ch, CURLOPT_REFERER, HTTP."/cgi/users/home?screen=User%3A%3AEdit&userid=$user_id&_action_null=Modify+profile");
			curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/users/home#t");
			$result = curl_exec ($ch);
				
			// looking for errors
			$xml = new SimpleXMLElement($result);
			$result = $xml->xpath("//div[@class='ep_msg_warning_content']//li");
			
			if($result === false ) {
				// all fine
				
				// save new pwd (if needed)
				if(!empty($_POST[$pwd_field])) {
					$_SESSION['password'] = Security::crypt_string($_POST[$pwd_field]);
					$this->password = $_POST[$pwd_field];
				}
				
				return true;
			} else {

				$this->error = Content::ERROR_SAVE;
				return false;
			
			}

		}		

	
		$this->error = Content::ERROR_SAVE;
		return false;
	
	}	


	/* write a comment */
	function write_comment($id, array $post_data, $code = null) {
	
		$this->error = null;

		
		//  create post data string and prevent url encoding issues
		$new_post_data = "";
		foreach($post_data as $param => $value) {
			if($post_data == "") {
				$new_post_data .= $param."=".(urlencode($value));
			} else {
				$new_post_data .= "&".$param."=".(urlencode($value));
			}
		}
		
		$ch = $this->init();
		
		// logged users DON'T need captcha
		if($this->isLogged) {
			$user_id = $this->get_user_id($this->username, $this->password, &$ch);
				
			// found
			if($user_id !== false) {
			
				// write comment
				curl_setopt ($ch, CURLOPT_POSTFIELDS, $new_post_data);
				curl_setopt ($ch, CURLOPT_POST, 1);
				curl_setopt ($ch, CURLOPT_REFERER, HTTP."/$id/");
				curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/users/comment/0/EPrint/Add");
				$result = curl_exec ($ch);
				
				return true;
				
			}

		} else {
			
			// captcha error
			
			
			if(strtolower($code) != strtolower($post_data["captcha"])) {
				$this->error = Content::ERROR_CAPTCHA;
				return false;
			}
			
			$user_id = $this->get_user_id(ANONYMOUS_USER_EMAIL, ANONYMOUS_USER_PWD, &$ch);
				echo $user_id;
			// found                  
			if($user_id !== false) {
			
				// write comment
				curl_setopt ($ch, CURLOPT_POSTFIELDS, $new_post_data);
				curl_setopt ($ch, CURLOPT_POST, 1);
				curl_setopt ($ch, CURLOPT_REFERER, HTTP."/$id/");
				curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/users/comment/0/EPrint/Add");
				$result = curl_exec ($ch);
				
				return true;
				
			}
		
		}

	
		$this->error = Content::ERROR_SAVE;
		return false;
	
	}	


	/* Update or Delete a comment */
	function update_comment(array $post_data) {
	
		$this->error = null;

		
		//  create post data string and prevent url encoding issues
		$new_post_data = "";
		foreach($post_data as $param => $value) {
			if($post_data == "") {
				$new_post_data .= $param."=".(urlencode($value));
			} else {
				$new_post_data .= "&".$param."=".(urlencode($value));
			}
		}
		$post_data = $new_post_data;
		
		
		$ch = $this->init();
		$user_id = $this->get_user_id($this->username, $this->password, &$ch);
			
		// found
		if($user_id !== false) {
		
			// write comment
			curl_setopt ($ch, CURLOPT_POSTFIELDS, $new_post_data);
			curl_setopt ($ch, CURLOPT_POST, 1);
			curl_setopt ($ch, CURLOPT_REFERER, HTTP."/$id/");
			curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/users/comment/0/EPrint/Update");
			$result = curl_exec ($ch);
			
			return true;
		
	
		}
	
		$this->error = Content::ERROR_SAVE;
		return false;
	
	}
	
	/* save a search */
	function save_search($url) {
	
		$this->error = null;
		
		$ch = $this->init();
		$user_id = $this->get_user_id($this->username, $this->password, &$ch);
			
		// found
		if($user_id !== false) {
		
			// get cached search id
			curl_setopt ($ch, CURLOPT_REFERER, HTTP."/$id/");
			curl_setopt ($ch, CURLOPT_URL, $url);
			$result = curl_exec ($ch);
			
			$xml = new SimpleXMLElement($result);
			if($xml) {
			
				$search_link = $xml->xpath("//span[@class='save-search']/a");
				if($search_link) {
				
					$attr = $search_link[0]->attributes();
					curl_setopt ($ch, CURLOPT_REFERER, $url);
					curl_setopt ($ch, CURLOPT_URL, (string)$attr["href"]);
					
					$result = curl_exec ($ch);
					
					if(substr_count($result, "Successfully stored search") > 0) {
					
						return true;
					
					}

				}
			
			}
			
			
		}
	
		$this->error = Content::ERROR_SAVE;
		return false;
	
	}	
	
	/* Get Saved Searches */
	function get_saved_searches() {
	
		$this->error = null;
		
		$ch = $this->init();
		$user_id = $this->get_user_id($this->username, $this->password, &$ch);
			
		// found
		if($user_id !== false) {
		
			$searches = array();
			
			curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/users/export_savedsearches/XML");			
			$result = curl_exec ($ch);
			
			if($result !== false) {
			
				$xml = new SimpleXMLElement($result);
				if($xml) {
					
					if(count($xml) > 0) {
					
						foreach($xml as $item) {
						
							$tmp = explode("|", (string)$item->spec);
							
							// find out if it's a search or a SINGLE PICTURE SAVED (it's a search by EPRINTID)
							$eprintid 	= "";
							$q			= "";
							$collection = "";
							if(strpos($tmp[5], "eprintid") === 0) { // single image
								$tmp2 		= explode(":", (string)$tmp[5]);
								$eprintid 	= $tmp2[count($tmp2)-1];
							} else if(substr_count((string)$item->spec, "collection:collection") > 0) { // collection
								$collection = str_replace("collection:collection:ANY:EQ:", "", $tmp[5]);
								// if also "q"
								if(strpos($tmp[6], "q") === 0) {
									$tmp2 	= explode("/", (string)$tmp[6]);
									$tmp3 	= explode(":", (string)$tmp2[6]);
									$q 		= $tmp3[count($tmp3)-1];
								}
								
							} else { // standard search
								$tmp2 	= explode("/", (string)$tmp[5]);
								$tmp3 	= explode(":", (string)$tmp2[6]);
								$q 		= $tmp3[count($tmp3)-1];
							}
						
							$search = array(
								'id'		=> (string)$item->id,
								'user'		=> (string)$user_id,
								'title'		=> (string)$item->name,
								'q'			=> $q,
								'eprintid'	=> $eprintid,
								'collection'=> $collection,
								'order'		=> $tmp[2],
								'frequency'	=> (string)$item->frequency,
								'mail'		=> (string)$item->mailempty,
								'public'	=> (string)$item->public
							);
							array_push($searches, $search);
						
						}

						return $searches;
					
					}
					
					
				}
			
			}
			
		}
	
		$this->error = Content::ERROR_SAVE;
		return false;
	
	}
	
	/* get saved search */
	function get_saved_search($id) {
	
		$id = (int)$id;
		
		$this->error = null;
		
		$ch = $this->init();
		$user_id = $this->get_user_id($this->username, $this->password, &$ch);
			
		// found
		if($user_id !== false) {
		
			$searches = array();
			
			curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/users/export_savedsearches/XML/".$id);			
			$result = curl_exec ($ch);
			
			if($result !== false) {
			
				$xml = new SimpleXMLElement($result);
				if($xml) {
					
					$attr = $xml->attributes();
					
					if((string)$attr->id == HTTP."/id/saved_search/".$id) {
					
						
						$tmp = explode("|", (string)$xml->spec);
						
						// find out if it's a search or a SINGLE PICTURE SAVED (it's a search by EPRINTID)
						$eprintid 	= "";
						$q			= "";
						if(strpos($tmp[5], "eprintid") === 0) {
							$tmp2 		= explode(":", (string)$tmp[5]);
							$eprintid 	= $tmp2[count($tmp2)-1];
						} else {
							$tmp2 	= explode("/", (string)$tmp[5]);
							$tmp3 	= explode(":", (string)$tmp2[6]);
							$q 		= $tmp3[count($tmp3)-1];
						}
					
						$search = array(
							'id'		=> (string)$xml->id,
							'user'		=> (string)$user_id,
							'title'		=> (string)$xml->name,
							'q'			=> $q,
							'eprintid'	=> $eprintid,
							'order'		=> $tmp[2],
							'frequency'	=> (string)$xml->frequency,
							'mail'		=> (string)$xml->mailempty,
							'public'	=> (string)$xml->public
						);

						return $search;
					
					}
					
					
				}
			
			}
			
		}
	
		$this->error = Content::ERROR_SAVE;
		return false;
	}
	
	/* Remove saved search */
	function remove_search($id) {
	
		$id = (int)$id;
		
		$this->error = null;
		
		$ch = $this->init();
		$user_id = $this->get_user_id($this->username, $this->password, &$ch);
			
		// found
		if($user_id !== false) {
		
			// try remove search
			curl_setopt ($ch, CURLOPT_REFERER, HTTP."/cgi/users/home?screen=User%3A%3ASavedSearch%3A%3ARemove&userid=".$user_id."&savedsearchid=".$id."&_action_null=Remove");
			curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/users/home#t");
			
			curl_setopt ($ch, CURLOPT_POSTFIELDS, "savedsearchid=".$id."&userid=".$user_id."&screen=User::SavedSearch::Remove&_action_remove=Yes, delete it");
			curl_setopt ($ch, CURLOPT_POST, 1);
			$result = curl_exec ($ch);
			
			if(substr_count($result, "Removed saved search") > 0) {
			
				return true;
			
			}
				
		}
	
		$this->error = Content::ERROR_SAVE;
		return false;

	
	}


	/*Update search */
	function update_saved_search(array $post_data) {
	
		//  create post data string and prevent url encoding issues
		$new_post_data = "";
		foreach($post_data as $param => $value) {
			if($post_data == "") {
				$new_post_data .= $param."=".(urlencode($value));
			} else {
				$new_post_data .= "&".$param."=".(urlencode($value));
			}
		}
		$post_data = $new_post_data;
		
		$this->error = null;
		
		$ch = $this->init();
		$user_id = $this->get_user_id($this->username, $this->password, &$ch);
			
		// found
		if($user_id !== false) {
		
			// try remove search
			curl_setopt ($ch, CURLOPT_REFERER, HTTP."/cgi/users/home?screen=User%3A%3ASavedSearch%3A%3ARemove&userid=".$user_id."&savedsearchid=".$id."&_action_null=Settings");
			curl_setopt ($ch, CURLOPT_URL, HTTP."/cgi/users/home#t");
			curl_setopt ($ch, CURLOPT_POSTFIELDS, $post_data);
			curl_setopt ($ch, CURLOPT_POST, 1);
			$result = curl_exec ($ch);
			
			if(substr_count($result, "Edit:no_such_saved_search") == 0) {
				return true;
			}
				
		}
	
		$this->error = Content::ERROR_SAVE;
		return false;		
		
	
	}


}

?>
